/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef OHMW_FRAMEWORK_CXX_BINCODE_DECODER_H
#define OHMW_FRAMEWORK_CXX_BINCODE_DECODER_H

#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include "Endian.h"

#define DEFINE_GET_UNCHECKED(Type) \
    void GetUnchecked(const std::vector<uint8_t>& buffer, Type& value) override { \
        uint8_t tmp[sizeof(Type)]; \
        GetUnchecked(buffer, tmp, sizeof(Type)); \
        value = *reinterpret_cast<Type*>(tmp); \
        value = le2host(value); \
    }

#define DEFINE_GET(Type) \
    bool Get(const std::vector<uint8_t>& buffer, Type& value) override { \
        uint8_t tmp[sizeof(Type)]; \
        if (!Get(buffer, tmp, sizeof(Type))) { \
            return false; \
        } \
        value = *reinterpret_cast<Type*>(tmp); \
        value = le2host(value); \
        return true; \
    }

namespace OHOS {
namespace OHMW {
class Decoder {
public:
    virtual ~Decoder() {}

    virtual bool Get(const std::vector<uint8_t> &buffer, bool &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, char &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, uint8_t &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, uint16_t &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, uint32_t &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, uint64_t &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, int8_t &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, int16_t &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, int32_t &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, int64_t &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, float &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, double &value) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, uint8_t* bytes, size_t len) = 0;
    virtual bool Get(const std::vector<uint8_t> &buffer, std::string &s) = 0;

    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, bool &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, char &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, uint8_t &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, uint16_t &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, uint32_t &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, uint64_t &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, int8_t &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, int16_t &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, int32_t &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, int64_t &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, float &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, double &value) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, uint8_t* bytes, size_t len) = 0;
    virtual void GetUnchecked(const std::vector<uint8_t> &buffer, std::string &s) = 0;
};

class DefaultDecoder : public Decoder {
public:
    DefaultDecoder() = default;
    DefaultDecoder(size_t offset) : offset_(offset) {}
    DefaultDecoder(const DefaultDecoder&) = default;
    DefaultDecoder& operator=(const DefaultDecoder&) = default;
    DefaultDecoder(DefaultDecoder&&) = default;
    DefaultDecoder& operator=(DefaultDecoder&&) = default;
    ~DefaultDecoder() override = default;

    bool Get(const std::vector<uint8_t> &buffer, bool &value) override {
        uint8_t tmp;
        if (!Get(buffer, tmp)) {
            return false;
        }
        value = static_cast<bool>(tmp);
        return true;
    }

    bool Get(const std::vector<uint8_t> &buffer, char &value) override {
        uint8_t tmp;
        if (!Get(buffer, tmp)) {
            return false;
        }
        value = static_cast<char>(tmp);
        return true;
    }

    bool Get(const std::vector<uint8_t> &buffer, uint8_t &value) override {
        if (offset_ >= buffer.size()) {
            return false;
        }
        value = buffer[offset_];
        offset_ += 1;
        return true;
    }

    DEFINE_GET(uint16_t)
    DEFINE_GET(uint32_t)
    DEFINE_GET(uint64_t)

    bool Get(const std::vector<uint8_t> &buffer, int8_t &value) override {
        uint8_t tmp;
        if (!Get(buffer, tmp)) {
            return false;
        }
        value = static_cast<int8_t>(tmp);
        return true;
    }

    DEFINE_GET(int16_t)
    DEFINE_GET(int32_t)
    DEFINE_GET(int64_t)
    DEFINE_GET(float)
    DEFINE_GET(double)

    bool Get(const std::vector<uint8_t> &buffer, uint8_t* bytes, size_t len) override {
        if (offset_ >= buffer.size()) {
            return false;
        }
        GetUnchecked(buffer, bytes, len);
        return true;
    }

    bool Get(const std::vector<uint8_t> &buffer, std::string &s) override {
        uint32_t len;
        if (offset_ >= buffer.size()) {
            return false;
        }
        Get(buffer, len);
        s.resize(len);
        Get(buffer, reinterpret_cast<uint8_t*>(&s[0]), len);
        return true;
    }

    void GetUnchecked(const std::vector<uint8_t> &buffer, bool &value) override {
        uint8_t tmp;
        GetUnchecked(buffer, tmp);
        value = static_cast<bool>(tmp);
    }

    void GetUnchecked(const std::vector<uint8_t> &buffer, char &value) override {
        uint8_t tmp;
        GetUnchecked(buffer, tmp);
        value = static_cast<char>(tmp);
    }

    void GetUnchecked(const std::vector<uint8_t> &buffer, uint8_t &value) override {
        value = buffer[offset_];
        offset_ += 1;
    }

    DEFINE_GET_UNCHECKED(uint16_t)
    DEFINE_GET_UNCHECKED(uint32_t)
    DEFINE_GET_UNCHECKED(uint64_t)

    void GetUnchecked(const std::vector<uint8_t> &buffer, int8_t &value) override {
        uint8_t tmp;
        GetUnchecked(buffer, tmp);
        value = static_cast<int8_t>(tmp);
    }

    DEFINE_GET_UNCHECKED(int16_t)
    DEFINE_GET_UNCHECKED(int32_t)
    DEFINE_GET_UNCHECKED(int64_t)
    DEFINE_GET_UNCHECKED(float)
    DEFINE_GET_UNCHECKED(double)

    void GetUnchecked(const std::vector<uint8_t> &buffer, uint8_t* bytes, size_t len) override {
        __builtin_memcpy(bytes, buffer.data() + offset_, len);
        offset_ += len;
    }

    void GetUnchecked(const std::vector<uint8_t> &buffer, std::string &s) override {
        uint32_t len;
        GetUnchecked(buffer, len);
        s.resize(len);
        GetUnchecked(buffer, reinterpret_cast<uint8_t*>(&s[0]), len);
    }

private:
    size_t offset_ = 0;
};
}
}

#endif
